Deutsch

Eine tiefgehende Untersuchung von Tornado, einem Python-Webframework und einer asynchronen Netzwerkbibliothek. Lernen Sie, wie man skalierbare, hochleistungsfähige Anwendungen mit detaillierten Erklärungen, Beispielen und Best Practices erstellt.

Tornado-Dokumentation: Ein umfassender Leitfaden für Entwickler weltweit

Tornado ist ein Python-Webframework und eine asynchrone Netzwerkbibliothek, die ursprünglich bei FriendFeed entwickelt wurde. Es eignet sich besonders gut für Long-Polling, WebSockets und andere Anwendungen, die eine langlebige Verbindung zu jedem Benutzer erfordern. Seine nicht-blockierende Netzwerk-E/A macht es extrem skalierbar und zu einer leistungsstarken Wahl für die Erstellung hochperformanter Webanwendungen. Dieser umfassende Leitfaden führt Sie durch die Kernkonzepte von Tornado und bietet praktische Beispiele, um Ihnen den Einstieg zu erleichtern.

Was ist Tornado?

Im Kern ist Tornado ein Webframework und eine asynchrone Netzwerkbibliothek. Im Gegensatz zu traditionellen synchronen Webframeworks verwendet Tornado eine single-threaded, event-loop-basierte Architektur. Das bedeutet, dass es viele gleichzeitige Verbindungen verarbeiten kann, ohne einen Thread pro Verbindung zu benötigen, was es effizienter und skalierbarer macht.

Hauptmerkmale von Tornado:

Einrichten Ihrer Tornado-Umgebung

Bevor Sie in die Tornado-Entwicklung eintauchen, müssen Sie Ihre Umgebung einrichten. Hier ist eine Schritt-für-Schritt-Anleitung:

  1. Python installieren: Stellen Sie sicher, dass Sie Python 3.6 oder höher installiert haben. Sie können es von der offiziellen Python-Website (python.org) herunterladen.
  2. Eine virtuelle Umgebung erstellen (empfohlen): Verwenden Sie venv oder virtualenv, um eine isolierte Umgebung für Ihr Projekt zu erstellen:
    python3 -m venv myenv
    source myenv/bin/activate  # Unter Linux/macOS
    myenv\Scripts\activate  # Unter Windows
  3. Tornado installieren: Installieren Sie Tornado mit pip:
    pip install tornado

Ihre erste Tornado-Anwendung

Lassen Sie uns eine einfache "Hallo, Welt!"-Anwendung mit Tornado erstellen. Erstellen Sie eine Datei namens app.py und fügen Sie den folgenden Code hinzu:

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
 def get(self):
  self.write("Hello, World!")

def make_app():
 return tornado.web.Application([
  (r"/", MainHandler),
 ])

if __name__ == "__main__":
 app = make_app()
 app.listen(8888)
 tornado.ioloop.IOLoop.current().start()

Führen Sie die Anwendung nun von Ihrem Terminal aus:

python app.py

Öffnen Sie Ihren Webbrowser und navigieren Sie zu http://localhost:8888. Sie sollten die "Hallo, Welt!"-Nachricht sehen.

Erläuterung:

Request Handler und Routing

Request Handler sind die Grundlage von Tornado-Webanwendungen. Sie definieren, wie eingehende HTTP-Anfragen basierend auf der URL behandelt werden. Das Routing ordnet URLs bestimmten Request Handlern zu.

Definieren von Request Handlern:

Um einen Request Handler zu erstellen, leiten Sie von tornado.web.RequestHandler ab und implementieren die entsprechenden HTTP-Methoden (get, post, put, delete, usw.).

class MyHandler(tornado.web.RequestHandler):
 def get(self):
  self.write("This is a GET request.")

 def post(self):
  data = self.request.body.decode('utf-8')
  self.write(f"Received POST data: {data}")

Routing:

Das Routing wird bei der Erstellung der tornado.web.Application konfiguriert. Sie geben eine Liste von Tupeln an, wobei jedes Tupel ein URL-Muster und den entsprechenden Request Handler enthält.

app = tornado.web.Application([
 (r"/", MainHandler),
 (r"/myhandler", MyHandler),
])

URL-Muster:

URL-Muster sind reguläre Ausdrücke. Sie können Gruppen regulärer Ausdrücke verwenden, um Teile der URL zu erfassen und sie als Argumente an die Methoden des Request Handlers zu übergeben.

class UserHandler(tornado.web.RequestHandler):
 def get(self, user_id):
  self.write(f"User ID: {user_id}")

app = tornado.web.Application([
 (r"/user/([0-9]+)", UserHandler),
])

In diesem Beispiel passt /user/([0-9]+) auf URLs wie /user/123. Der Teil ([0-9]+) erfasst eine oder mehrere Ziffern und übergibt sie als user_id-Argument an die get-Methode des UserHandler.

Templating

Tornado enthält eine einfache und effiziente Templating-Engine. Templates werden verwendet, um HTML dynamisch zu generieren und die Präsentationslogik von der Anwendungslogik zu trennen.

Erstellen von Templates:

Templates werden typischerweise in separaten Dateien gespeichert (z.B. index.html). Hier ist ein einfaches Beispiel:

<!DOCTYPE html>
<html>
<head>
 <title>Meine Webseite</title>
</head>
<body>
 <h1>Willkommen, {{ name }}!</h1>
 <p>Heute ist {{ today }}.</p>
</body>
</html>

{{ name }} und {{ today }} sind Platzhalter, die beim Rendern des Templates durch tatsächliche Werte ersetzt werden.

Rendern von Templates:

Um ein Template zu rendern, verwenden Sie die Methode render() in Ihrem Request Handler:

class TemplateHandler(tornado.web.RequestHandler):
 def get(self):
  name = "John Doe"
  today = "2023-10-27"
  self.render("index.html", name=name, today=today)

Stellen Sie sicher, dass die Einstellung template_path in Ihren Anwendungseinstellungen korrekt konfiguriert ist. Standardmäßig sucht Tornado nach Templates in einem Verzeichnis namens templates im selben Verzeichnis wie Ihre Anwendungsdatei.

app = tornado.web.Application([
 (r"/template", TemplateHandler),
], template_path="templates")

Template-Syntax:

Tornado-Templates unterstützen verschiedene Funktionen, darunter:

Asynchrone Operationen

Die Stärke von Tornado liegt in seinen asynchronen Fähigkeiten. Asynchrone Operationen ermöglichen es Ihrer Anwendung, nicht-blockierende E/A durchzuführen, was die Leistung und Skalierbarkeit verbessert. Dies ist besonders nützlich für Aufgaben, die das Warten auf externe Ressourcen beinhalten, wie z.B. Datenbankabfragen oder Netzwerkanfragen.

@tornado.gen.coroutine:

Der Dekorator @tornado.gen.coroutine ermöglicht es Ihnen, asynchronen Code mit dem Schlüsselwort yield zu schreiben. Dadurch sieht asynchroner Code eher wie synchroner Code aus und verhält sich auch so, was die Lesbarkeit und Wartbarkeit verbessert.

import tornado.gen
import tornado.httpclient

class AsyncHandler(tornado.web.RequestHandler):
 @tornado.gen.coroutine
 def get(self):
  http_client = tornado.httpclient.AsyncHTTPClient()
  response = yield http_client.fetch("http://example.com")
  self.write(response.body.decode('utf-8'))

In diesem Beispiel ist http_client.fetch() eine asynchrone Operation, die ein Future zurückgibt. Das Schlüsselwort yield unterbricht die Ausführung der Coroutine, bis das Future aufgelöst ist. Sobald das Future aufgelöst ist, wird die Coroutine fortgesetzt und der Antwortkörper an den Client geschrieben.

tornado.concurrent.Future:

Ein Future repräsentiert das Ergebnis einer asynchronen Operation, das möglicherweise noch nicht verfügbar ist. Sie können Future-Objekte verwenden, um asynchrone Operationen miteinander zu verketten und Fehler zu behandeln.

tornado.ioloop.IOLoop:

Die IOLoop ist das Herzstück der asynchronen Engine von Tornado. Sie überwacht Dateideskriptoren und Sockets auf Ereignisse und leitet sie an die entsprechenden Handler weiter. Normalerweise müssen Sie nicht direkt mit der IOLoop interagieren, aber es ist wichtig, ihre Rolle bei der Handhabung asynchroner Operationen zu verstehen.

WebSockets

Tornado bietet eine hervorragende Unterstützung für WebSockets, die eine Echtzeitkommunikation zwischen dem Server und den Clients ermöglichen. WebSockets sind ideal für Anwendungen, die eine bidirektionale Kommunikation mit geringer Latenz erfordern, wie z.B. Chat-Anwendungen, Online-Spiele und Echtzeit-Dashboards.

Erstellen eines WebSocket-Handlers:

Um einen WebSocket-Handler zu erstellen, leiten Sie von tornado.websocket.WebSocketHandler ab und implementieren die folgenden Methoden:

import tornado.websocket

class WebSocketHandler(tornado.websocket.WebSocketHandler):
 def open(self):
  print("WebSocket opened")

 def on_message(self, message):
  self.write_message(f"You sent: {message}")

 def on_close(self):
  print("WebSocket closed")

 def check_origin(self, origin):
  return True # Cross-Origin-WebSocket-Verbindungen aktivieren

Integrieren von WebSockets in Ihre Anwendung:

Fügen Sie den WebSocket-Handler zur Routing-Konfiguration Ihrer Anwendung hinzu:

app = tornado.web.Application([
 (r"/ws", WebSocketHandler),
])

Clientseitige Implementierung:

Auf der Client-Seite können Sie JavaScript verwenden, um eine WebSocket-Verbindung herzustellen und Nachrichten zu senden/empfangen:

const websocket = new WebSocket("ws://localhost:8888/ws");

websocket.onopen = () => {
 console.log("WebSocket-Verbindung hergestellt");
 websocket.send("Hallo vom Client!");
};

websocket.onmessage = (event) => {
 console.log("Nachricht empfangen:", event.data);
};

websocket.onclose = () => {
 console.log("WebSocket-Verbindung geschlossen");
};

Authentifizierung und Sicherheit

Sicherheit ist ein entscheidender Aspekt der Webanwendungsentwicklung. Tornado bietet mehrere Funktionen, die Ihnen helfen, Ihre Anwendungen zu sichern, einschließlich Authentifizierung, Autorisierung und Schutz vor gängigen Web-Schwachstellen.

Authentifizierung:

Authentifizierung ist der Prozess der Überprüfung der Identität eines Benutzers. Tornado bietet integrierte Unterstützung für verschiedene Authentifizierungsschemata, darunter:

Autorisierung:

Autorisierung ist der Prozess, bei dem festgestellt wird, ob ein Benutzer die Berechtigung hat, auf eine bestimmte Ressource zuzugreifen. Sie können Autorisierungslogik in Ihren Request Handlern implementieren, um den Zugriff basierend auf Benutzerrollen oder Berechtigungen zu beschränken.

Best Practices für die Sicherheit:

Deployment

Das Deployment einer Tornado-Anwendung umfasst mehrere Schritte, einschließlich der Konfiguration eines Webservers, der Einrichtung eines Prozessmanagers und der Leistungsoptimierung.

Webserver:

Sie können Tornado hinter einem Webserver wie Nginx oder Apache bereitstellen. Der Webserver fungiert als Reverse-Proxy und leitet eingehende Anfragen an die Tornado-Anwendung weiter.

Prozessmanager:

Ein Prozessmanager wie Supervisor oder systemd kann verwendet werden, um den Tornado-Prozess zu verwalten und sicherzustellen, dass er bei einem Absturz automatisch neu gestartet wird.

Leistungsoptimierung:

Internationalisierung (i18n) und Lokalisierung (l10n)

Beim Erstellen von Anwendungen für ein globales Publikum ist es wichtig, Internationalisierung (i18n) und Lokalisierung (l10n) zu berücksichtigen. i18n ist der Prozess, eine Anwendung so zu gestalten, dass sie ohne technische Änderungen an verschiedene Sprachen und Regionen angepasst werden kann. l10n ist der Prozess der Anpassung einer internationalisierten Anwendung für eine bestimmte Sprache oder Region durch Hinzufügen von gebietsschemaspezifischen Komponenten und Übersetzen von Text.

Tornado und i18n/l10n

Tornado selbst hat keine eingebauten i18n/l10n-Bibliotheken. Sie können jedoch problemlos Standard-Python-Bibliotheken wie `gettext` oder anspruchsvollere Frameworks wie Babel integrieren, um i18n/l10n in Ihrer Tornado-Anwendung zu handhaben.

Beispiel mit `gettext`:

1. **Richten Sie Ihre Locales ein:** Erstellen Sie Verzeichnisse für jede Sprache, die Sie unterstützen möchten, die Nachrichtenkataloge (normalerweise `.mo`-Dateien) enthalten.

locales/
 en/LC_MESSAGES/messages.mo
 fr/LC_MESSAGES/messages.mo
 de/LC_MESSAGES/messages.mo

2. **Extrahieren Sie übersetzbare Zeichenketten:** Verwenden Sie ein Werkzeug wie `xgettext`, um übersetzbare Zeichenketten aus Ihrem Python-Code in eine `.po`-Datei (Portable Object) zu extrahieren. Diese Datei enthält die Originalzeichenketten und Platzhalter für Übersetzungen.

xgettext -d messages -o locales/messages.po your_tornado_app.py

3. **Übersetzen Sie die Zeichenketten:** Übersetzen Sie die Zeichenketten in den `.po`-Dateien für jede Sprache.

4. **Kompilieren Sie die Übersetzungen:** Kompilieren Sie die `.po`-Dateien in `.mo`-Dateien (Machine Object), die von `gettext` zur Laufzeit verwendet werden.

msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo

5. **Integrieren Sie es in Ihre Tornado-Anwendung:**

import gettext
import locale
import os
import tornado.web

class BaseHandler(tornado.web.RequestHandler):
 def initialize(self):
  try:
  locale.setlocale(locale.LC_ALL, self.get_user_locale().code)
  except locale.Error:
  # Behandeln Sie Fälle, in denen die Locale vom System nicht unterstützt wird
  print(f"Locale {self.get_user_locale().code} not supported")

  translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
  translation.install()
  self._ = translation.gettext

 def get_current_user_locale(self):
  # Logik zur Bestimmung der Locale des Benutzers (z. B. aus dem Accept-Language-Header, Benutzereinstellungen usw.)
  # Dies ist ein vereinfachtes Beispiel - Sie benötigen eine robustere Lösung
  accept_language = self.request.headers.get('Accept-Language', 'en')
  return tornado.locale.get(accept_language.split(',')[0].split(';')[0])

class MainHandler(BaseHandler):
 def get(self):
  self.render("index.html", _=self._)

settings = {
 "template_path": os.path.join(os.path.dirname(__file__), "templates"),
}

app = tornado.web.Application([
 (r"/", MainHandler),
], **settings)

6. **Ändern Sie Ihre Templates:** Verwenden Sie die Funktion `_()` (gebunden an `gettext.gettext`), um Zeichenketten für die Übersetzung in Ihren Templates zu markieren.

<h1>{{ _("Willkommen auf unserer Webseite!") }}</h1>
<p>{{ _("Dies ist ein übersetzter Absatz.") }}</p>

Wichtige Überlegungen für ein globales Publikum:

Fortgeschrittene Themen

Benutzerdefinierte Fehlerseiten:

Sie können die Fehlerseiten anpassen, die Tornado anzeigt, wenn ein Fehler auftritt. Dies ermöglicht es Ihnen, eine benutzerfreundlichere Erfahrung zu bieten und Debugging-Informationen einzuschließen.

Benutzerdefinierte Einstellungen:

Sie können benutzerdefinierte Einstellungen in Ihrer Anwendungskonfiguration definieren und in Ihren Request Handlern darauf zugreifen. Dies ist nützlich zum Speichern von anwendungsspezifischen Parametern wie Datenbankverbindungszeichenfolgen oder API-Schlüsseln.

Testen:

Testen Sie Ihre Tornado-Anwendungen gründlich, um sicherzustellen, dass sie korrekt und sicher funktionieren. Verwenden Sie Unit-Tests, Integrationstests und End-to-End-Tests, um alle Aspekte Ihrer Anwendung abzudecken.

Fazit

Tornado ist ein leistungsstarkes und vielseitiges Webframework, das sich gut für die Erstellung skalierbarer, hochleistungsfähiger Webanwendungen eignet. Seine asynchrone Architektur, WebSocket-Unterstützung und benutzerfreundliche API machen es zu einer beliebten Wahl für Entwickler weltweit. Indem Sie den Richtlinien und Beispielen in diesem umfassenden Leitfaden folgen, können Sie mit dem Erstellen Ihrer eigenen Tornado-Anwendungen beginnen und von seinen vielen Funktionen profitieren.

Denken Sie daran, die offizielle Tornado-Dokumentation für die aktuellsten Informationen und Best Practices zu konsultieren. Viel Spaß beim Codieren!

Tornado-Dokumentation: Ein umfassender Leitfaden für Entwickler weltweit | MLOG